#include "StaticBNF.h"

StaticBNF::StaticBNF(std::map<std::string, std::string> & m)
{
  varmap = m;
  this->createScannerMap();
}

StaticBNF::StaticBNF(StaticBNF & p) : IBNF()
{
  if (this != &p)
    *this = p;
}

StaticBNF &	StaticBNF::operator=(StaticBNF & p)
{
  this->library = p.library;
  return *this;
}

StaticBNF::~StaticBNF()
{
}

void		StaticBNF::tokenize(const std::string & str,
				    std::vector<std::string> & tokens,
				    const std::string & delimiters)
{
  std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
  std::string::size_type pos     = str.find_first_of(delimiters, lastPos);

  while (std::string::npos != pos || std::string::npos != lastPos)
    {
      tokens.push_back(str.substr(lastPos, pos - lastPos));
      lastPos = str.find_first_not_of(delimiters, pos);
      pos = str.find_first_of(delimiters, lastPos);
    }
}

StaticBNF::lex *	StaticBNF::scan(std::string & str)
{
  for (std::list<lex *>::iterator it = this->library.begin();
       it != this->library.end(); ++it)
    {
      if (str.find((*it)->lol) != std::string::npos)
	return *it;
    }
  return NULL;
}

bool		StaticBNF::check(std::string & str, lex *l)
{
  if (!l->lol_end.empty())
    {
      size_t pos = str.find(l->lol_end);
      if (pos != std::string::npos)
	str.erase(str.begin() + pos, str.end());
      else
	return false;
    }
  if (l->exp != NONE && l->exp != ELSE)
    {
      if (str.empty())
	return false;
    }
  else if(l->exp == NONE && !str.empty())
    return false;
  return true;
}

std::string	StaticBNF::translate(std::string str)
{
  lex *		l = this->scan(str);

  if (l != NULL)
    {
      std::string	rt;
      str.erase(str.begin(), str.begin() + l->lol.length());
      if (!this->check(str, l))
	return "";
      rt += l->cpp;
      if (l->do_convert == true)
	{
	  for (std::map<std::string, std::string>::iterator it = l->convert_args.begin();
	       it != l->convert_args.end(); ++it)
	    {
	      size_t pos = str.find((*it).first);
	      if (pos != std::string::npos)
		str.replace(pos, (*it).first.length(), (*it).second);
	    }
	}
      rt += str;
      rt += l->cpp_end;
      this->manageOperators(rt);
      return rt;
    }
  return "";
}

bool		StaticBNF::priority(std::string str)
{
  lex *		l = this->scan(str);

  return l->priority;
}
